package com.keba.lamp.file.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.keba.basic.base.service.impl.SuperServiceImpl;
import com.keba.basic.context.ContextUtil;
import com.keba.basic.exception.BizException;
import com.keba.basic.utils.ArgumentAssert;
import com.keba.basic.utils.BeanPlusUtil;
import com.keba.lamp.complaint.entity.ComFileRel;
import com.keba.lamp.complaint.service.ComFileRelService;
import com.keba.lamp.file.entity.File;
import com.keba.lamp.file.manager.FileManager;
import com.keba.lamp.file.properties.FileServerProperties;
import com.keba.lamp.file.service.FileService;
import com.keba.lamp.file.strategy.FileContext;
import com.keba.lamp.file.vo.param.FileUploadVO;
import com.keba.lamp.file.vo.result.FileResultVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 业务实现类
 * 增量文件上传日志
 * </p>
 *
 * @author tangyh
 * @date 2021-06-30
 * @create [2021-06-30] [tangyh] [初始创建]
 */
@Slf4j
@Service
@Transactional(readOnly = true)
public class FileServiceImpl extends SuperServiceImpl<FileManager, Long, File> implements FileService {
    @Resource
    private FileContext fileContext;
    @Resource
    private FileManager fileManager;
    @Resource
    private FileServerProperties fileServerProperties;
    @Resource
    private ComFileRelService comFileRelService;


    @Override
    public List<FileResultVO> listByBizIdAndBizType(Long bizId, String bizType) {
        ArgumentAssert.notNull(bizId, "请传入业务id");
        return superManager.listByBizIdAndBizType(bizId, bizType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileResultVO upload(MultipartFile file, FileUploadVO fileUploadVO) {
        // 忽略路径字段,只处理文件类型
        if (file.isEmpty()) {
            throw new BizException("请上传有效文件");
        }

        if (!fileServerProperties.validSuffix(file.getOriginalFilename())) {
            throw new BizException("文件后缀不支持");
        }
        if (StrUtil.containsAny(file.getOriginalFilename(), "../", "./")) {
            throw new BizException("文件名不能含有特殊字符");
        }

        File fileFile = fileContext.upload(file, fileUploadVO);
        fileFile.setTenantId(ContextUtil.getTenantId());

        List<File> imageFiles = new ArrayList<>();
        Integer pageCount = 1; //默认为1
        String suffix = FilenameUtils.getExtension(file.getOriginalFilename());
        if (BooleanUtil.isTrue(fileUploadVO.getSplitDoc()) && "pdf".equalsIgnoreCase(suffix)) {
            try {
                PDDocument document = PDDocument.load(file.getInputStream());
                //移除加密
                document.setAllSecurityToBeRemoved(true);
                // 获取总页数
                pageCount = document.getNumberOfPages();
                document.close();
            } catch (IOException e) {
                log.error("PDF文档读取失败", e);
                throw new BizException("PDF文档读取失败");
            }
            log.info("pdf转图片结果:{}", JSON.toJSONString(imageFiles));
        }
        fileManager.save(fileFile);
        if (BooleanUtil.isTrue(fileUploadVO.getSplitDoc()) && "pdf".equalsIgnoreCase(suffix)) {
            ComFileRel comFileRel = new ComFileRel();
            comFileRel.setComFileId(fileFile.getId());
            comFileRel.setPicNum(pageCount);
            //comFileRel.setExtendColumn(JSON.toJSONString(imageFiles));
            comFileRelService.save(comFileRel);
        }
        return BeanPlusUtil.toBean(fileFile, FileResultVO.class);
    }

    @Override
    public FileResultVO upload(InputStream file, String fileName, FileUploadVO fileUploadVO) {
        if (!fileServerProperties.validSuffix(fileName)) {
            throw new BizException("文件后缀不支持");
        }
        if (StrUtil.containsAny(fileName, "../", "./")) {
            throw new BizException("文件名不能含有特殊字符");
        }
        File fileFile = fileContext.upload(file, fileName, fileUploadVO);
        fileFile.setTenantId(ContextUtil.getTenantId());
        fileManager.save(fileFile);
        return BeanPlusUtil.toBean(fileFile, FileResultVO.class);
    }

    @Override
    public Map<String, String> findUrlByPath(List<String> paths) {
        return fileContext.findUrlByPath(paths);
    }

    @Override
    public Map<Long, String> findUrlById(List<Long> paths) {
        return fileContext.findUrlById(paths);
    }

    @Override
    public String findUrlById(Long id) {
        return fileContext.findUrlById(id);
    }

    @Override
    public String findUrlByFile(File file) {
        return fileContext.findUrlByFile(file);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return false;
        }
        List<File> list = list(Wrappers.<File>lambdaQuery().in(File::getId, ids));
        if (list.isEmpty()) {
            return false;
        }
        fileManager.removeByIds(ids);
        return fileContext.delete(list);
    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, List<Long> ids) throws Exception {
        List<File> list = fileManager.listByIds(ids);
        ArgumentAssert.notEmpty(list, "请配置正确的文件存储类型");
        fileContext.download(request, response, list);
    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, String packageName, List<Long> ids) throws Exception {
        List<File> list = fileManager.listByIds(ids);
        ArgumentAssert.notEmpty(list, "请配置正确的文件存储类型");
        fileContext.download(request, response, packageName, list);
    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, Long id) throws Exception {
        File file = fileManager.getById(id);
        ArgumentAssert.notNull(file, "请配置正确的文件存储类型");
        fileContext.download(request, response, file);
    }

}
